﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Web;
using System.Net;
using System.Globalization;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.XPath;

using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.Utilities;
using Kiiro.Common.Entities;
using Kiiro.ExceptionManagement;

using SPSiteDefinition = Kiiro.Common.Utility.Constants.SPSiteDefinition;
using SPListUrls = Kiiro.Common.Utility.Constants.SPListUrls;
using Permissions = Kiiro.Common.Utility.Constants.Permissions;

namespace Kiiro.Common.Utility
{
    public static class SPHelpers
    {
        public static string GetHostHeader ( HttpRequest request )
        {
            return "http://" + request.Headers [ "Host" ];
        }

        public static string GetAbsoluteUrl ( Guid siteCollectionId, string serverRelativeUrl )
        {
            string fullUrl = default ( string );

            try
            {
                using ( SPSite site = new SPSite ( siteCollectionId ) )
                {
                    fullUrl = site.MakeFullUrl ( serverRelativeUrl );
                }
            }
            catch
            {
            }

            return fullUrl;
        }

        public static string GetPortalAbsoluteUrl ( Guid siteCollectionId, string serverRelativeUrl )
        {
            string fullUrl = default ( string );

            using ( SPWeb web = GetPortalWeb ( siteCollectionId, serverRelativeUrl ) )
            {
                fullUrl = web.Url;
            }

            return fullUrl;
        }

        public static void GetSiteCollectionIdAndServerRelativeUrl ( string absUrl, out Guid siteCollectionId, out string serverRelativeUrl )
        {
            siteCollectionId = default ( Guid );
            serverRelativeUrl = default ( string );

            try
            {
                using ( SPSite site = new SPSite ( absUrl ) )
                {
                    siteCollectionId = site.ID;

                    using ( SPWeb web = site.OpenWeb ( ) )
                    {
                        serverRelativeUrl = web.ServerRelativeUrl;
                    }
                }
            }
            catch
            {
            }
        }

        public static string GenerateDocumentOnClick ( string documentUrl, string extension, bool canEdit, string requestUrl )
        {
            string onClick = string.Format ( "return DispEx(this,event,'TRUE','FALSE','FALSE','SharePoint.OpenDocuments.3','0','SharePoint.OpenDocuments','','','1071741823','{0}','0','0','0x7fffffffffffffff')", SPContext.Current.Web.CurrentUser.ID );

            if ( canEdit )
            {
                onClick = string.Format ( "return DispEx(this,event,'TRUE','FALSE','FALSE','','0','','','','','{0}','0','0','0x7fffffffffffffff')", SPContext.Current.Web.CurrentUser.ID );

                string ext = extension.ToLower ( );

                if ( ext == "doc" || ext == "docx" || ext == "mpp" || ext == "xls" || ext == "xlsx" || ext == "ppt" || ext == "pptx" || ext == "mdb" || ext == "vsd" )
                    onClick = string.Format ( "return editDocumentWithProgID2('{0}', '', 'SharePoint.OpenDocuments', '0', '{1}', '0')", documentUrl.Replace ( "'", "%27" ), requestUrl );
            }

            return onClick;
        }


        public static bool IsKiiro ( Guid siteCollectionId, string serverRelativeUrl )
        {
            bool isKiiro = false;
            using ( SPWeb web = GetWeb ( siteCollectionId, serverRelativeUrl ) )
            {
                isKiiro = IsKiiro ( web );
            }
            return isKiiro;
        }

        public static bool IsKiiro ( SPWeb web )
        {
            using ( SPSite site = new SPSite ( web.Url ) )
            {
                using ( SPWeb systemWeb = GetSystemWeb ( site.ID, web.ServerRelativeUrl ) )
                {
                    return systemWeb != null && systemWeb.WebTemplate == SPSiteDefinition.Name;
                }
            }
        }


        public static bool IsPortal ( Guid siteCollectionId, string serverRelativeUrl )
        {
            bool isPortal = false;
            using ( SPWeb web = GetWeb ( siteCollectionId, serverRelativeUrl ) )
            {
                isPortal = IsPortal ( web );
            }
            return isPortal;
        }

        public static bool IsPortal ( SPWeb web )
        {
            using ( SPSite site = new SPSite ( web.Url ) )
            {
                using ( SPWeb systemWeb = GetSystemWeb ( site.ID, web.ServerRelativeUrl ) )
                {
                    return systemWeb != null && systemWeb.WebTemplate == SPSiteDefinition.Name && systemWeb.Configuration == SPSiteDefinition.PortalId;
                }
            }
        }


        public static bool IsProject ( Guid siteCollectionId, string serverRelativeUrl )
        {
            bool isProject = false;
            using ( SPWeb web = GetWeb ( siteCollectionId, serverRelativeUrl ) )
            {
                isProject = IsProject ( web );
            }
            return isProject;
        }

        public static bool IsProject ( SPWeb web )
        {
            using ( SPSite site = new SPSite ( web.Url ) )
            {
                using ( SPWeb systemWeb = GetSystemWeb ( site.ID, web.ServerRelativeUrl ) )
                {
                    return systemWeb != null && systemWeb.WebTemplate == SPSiteDefinition.Name && systemWeb.Configuration == SPSiteDefinition.ProjectId;
                }
            }
        }


        public static SPWeb GetWeb ( Guid siteCollectionId, string serverRelativeUrl )
        {
            if ( serverRelativeUrl.Contains ( "/Lists/" ) )
            {
                serverRelativeUrl = serverRelativeUrl.Remove ( serverRelativeUrl.IndexOf ( "/Lists/" ) );
            }
            else if ( serverRelativeUrl.Contains ( "/Documents/" ) )
            {
                serverRelativeUrl = serverRelativeUrl.Remove ( serverRelativeUrl.IndexOf ( "/Documents/" ) );
            }

            using ( SPSite site = new SPSite ( siteCollectionId ) )
            {
                return site.OpenWeb ( serverRelativeUrl );
            }
        }

        public static SPWeb GetWeb ( Guid siteCollectionId, string serverRelativeUrl, string login )
        {
            if ( serverRelativeUrl.Contains ( "/Lists/" ) )
            {
                serverRelativeUrl = serverRelativeUrl.Remove ( serverRelativeUrl.IndexOf ( "/Lists/" ) );
            }
            else if ( serverRelativeUrl.Contains ( "/Documents/" ) )
            {
                serverRelativeUrl = serverRelativeUrl.Remove ( serverRelativeUrl.IndexOf ( "/Documents/" ) );
            }

            using ( SPWeb web = GetWeb ( siteCollectionId, serverRelativeUrl ) )
            {
                using ( SPSite site = new SPSite ( siteCollectionId, web.AllUsers [ login ].UserToken ) )
                {
                    return site.OpenWeb ( serverRelativeUrl );
                }
            }
        }


        public static SPWeb GetPortalWeb ( Guid siteCollectionId, string serverRelativeUrl )
        {
            SPWeb web = null;

            using ( SPWeb tempWeb = GetWeb ( siteCollectionId, serverRelativeUrl ) )
            {
                if ( IsProject ( tempWeb ) )
                    web = tempWeb.ParentWeb;
                else if ( IsPortal ( tempWeb ) )
                    web = GetWeb ( siteCollectionId, serverRelativeUrl );
                else
                    throw new Exception ( @"Can't GetPortalWeb when the context web is not part of Kiiro." );
            }

            return web;
        }

        public static SPWeb GetPortalWeb ( Guid siteCollectionId, string serverRelativeUrl, string login )
        {
            if ( serverRelativeUrl.Contains ( "/Lists/" ) )
            {
                serverRelativeUrl = serverRelativeUrl.Remove ( serverRelativeUrl.IndexOf ( "/Lists/" ) );
            }
            else if ( serverRelativeUrl.Contains ( "/Documents/" ) )
            {
                serverRelativeUrl = serverRelativeUrl.Remove ( serverRelativeUrl.IndexOf ( "/Documents/" ) );
            }

            using ( SPWeb web = GetWeb ( siteCollectionId, serverRelativeUrl ) )
            {
                using ( SPSite site = new SPSite ( siteCollectionId, web.AllUsers [ login ].UserToken ) )
                {
                    using ( SPWeb portalWeb = site.OpenWeb ( serverRelativeUrl ) )
                    {
                        if ( IsPortal ( portalWeb ) )
                            return site.OpenWeb ( serverRelativeUrl );
                        else
                            return site.OpenWeb ( portalWeb.ParentWebId );
                    }
                }
            }
        }


        public static SPSite GetSystemSite ( Guid siteCollectionId )
        {
            SPUserToken systemToken = null;

            using ( SPSite site = new SPSite ( siteCollectionId ) )
            {
                bool originalCADE = site.CatchAccessDeniedException;
                try
                {
                    site.CatchAccessDeniedException = false;
                    systemToken = site.SystemAccount.UserToken;
                }
                catch ( UnauthorizedAccessException )
                {
                    SPSecurity.RunWithElevatedPrivileges ( delegate ( )
                    {
                        using ( SPSite rwepSite = new SPSite ( siteCollectionId ) )
                        {
                            systemToken = rwepSite.SystemAccount.UserToken;
                        }
                    } );
                }
                finally
                {
                    site.CatchAccessDeniedException = originalCADE;
                }
            }

            return new SPSite ( siteCollectionId, systemToken );
        }

        public static SPWeb GetSystemWeb ( Guid siteCollectionId, string serverRelativeUrl )
        {
            using ( SPSite elevatedSite = GetSystemSite ( siteCollectionId ) )
            {
                return elevatedSite.OpenWeb ( serverRelativeUrl );
            }
        }


        public static string GetServerRelativeUrl ( SPWeb web )
        {
            string serverRelativeUrl = default ( string );

            using ( web )
            {
                serverRelativeUrl = GetServerRelativeUrl ( web, true );
            }

            return serverRelativeUrl;
        }

        public static string GetServerRelativeUrl ( SPWeb web, bool returnEmpty )
        {
            string serverRelativeUrl = string.Empty;// GetHostHeader ( );

            using ( web )
            {
                if ( web.ServerRelativeUrl != "/" || !returnEmpty )
                    serverRelativeUrl = web.ServerRelativeUrl;
            }

            return serverRelativeUrl;
        }

        public static string GetPortalServerRelativeUrl ( Guid siteCollectionId, string serverRelativeUrl )
        {
            string portalRelativeUrl = string.Empty;

            using ( SPWeb web = GetPortalWeb ( siteCollectionId, serverRelativeUrl ) )
            {
                portalRelativeUrl = GetServerRelativeUrl ( web );
            }

            return portalRelativeUrl;
        }

        public static string GetServerRelativeWebUrl ( Guid siteCollectionId, string serverRelativeUrl )
        {
            using ( SPWeb web = GetWeb ( siteCollectionId, serverRelativeUrl ) )
            {
                serverRelativeUrl = web.ServerRelativeUrl;
            }

            return serverRelativeUrl;
        }


        public static Guid GetSiteCollectionId ( SPWeb web )
        {
            Guid siteCollectionId = default ( Guid );

            using ( SPSite site = web.Site )
            {
                siteCollectionId = site.ID;
            }

            return siteCollectionId;
        }


        public static string GetWebTitle ( Guid siteCollectionId, string serverRelativeUrl )
        {
            string webTitle = "";

            using ( SPWeb web = GetWeb ( siteCollectionId, serverRelativeUrl ) )
            {
                webTitle = web.Title;
            }

            return webTitle;
        }


        public static Guid GetWebId ( Guid siteCollectionId, string serverRelativeUrl, bool getPortal )
        {
            Guid webId = default ( Guid );

            if ( siteCollectionId == Guid.Empty && string.IsNullOrEmpty ( serverRelativeUrl ) )
            {
                if ( SPContext.Current != null && SPContext.Current.Site != null && SPContext.Current.Web != null )
                {
                    siteCollectionId = SPContext.Current.Site.ID;
                    serverRelativeUrl = SPContext.Current.Web.ServerRelativeUrl.Length > 1 ? SPContext.Current.Web.ServerRelativeUrl : "";

                    using ( SPWeb web = getPortal ? GetPortalWeb ( siteCollectionId, serverRelativeUrl ) : GetWeb ( siteCollectionId, serverRelativeUrl ) )
                    {
                        webId = web.ID;
                    }
                }
                else
                {
                    throw new Exception ( "Can't get SPWeb.ID because SPContext is null" );
                }
            }
            else
            {
                using ( SPWeb web = getPortal ? GetPortalWeb ( siteCollectionId, serverRelativeUrl ) : GetWeb ( siteCollectionId, serverRelativeUrl ) )
                {
                    webId = web.ID;
                }
            }

            return webId;
        }

        public static Guid GetFarmId ( )
        {
            return SPFarm.Local.Id;
        }


        public static String EditQueryString ( string url, string param, string value )
        {
            string newUrl = null;
            string [ ] queryStrings = url.Split ( "&".ToCharArray ( ), StringSplitOptions.RemoveEmptyEntries );
            if ( url.ToUpper ( ).Contains ( "?" + param.ToUpper ( ) + "=" ) )
            {
                queryStrings [ 0 ] = queryStrings [ 0 ].Remove ( queryStrings [ 0 ].IndexOf ( "?" ) );

                if ( value != null )
                    queryStrings [ 0 ] += "?" + param + "=" + value;

                newUrl = queryStrings [ 0 ];

                for ( int i = 1; i < queryStrings.Length; i++ )
                {
                    newUrl += newUrl.Contains ( "?" ) ? "&" + queryStrings [ i ] : "?" + queryStrings [ i ];
                }
            }
            else if ( url.ToUpper ( ).Contains ( "&" + param.ToUpper ( ) + "=" ) )
            {
                newUrl = queryStrings [ 0 ];
                for ( int i = 1; i < queryStrings.Length; i++ )
                {
                    if ( queryStrings [ i ].ToUpper ( ).StartsWith ( param.ToUpper ( ) + "=" ) )
                    {
                        if ( value != null )
                            queryStrings [ i ] = param + "=" + value;
                        else
                            queryStrings [ i ] = string.Empty;
                    }
                    if ( !string.IsNullOrEmpty ( queryStrings [ i ] ) )
                        newUrl += "&" + queryStrings [ i ];
                }
            }
            else if ( value != null )
            {
                if ( url.Contains ( "?" ) )
                    newUrl += url + "&" + param + "=" + value;
                else
                    newUrl += url + "?" + param + "=" + value;
            }
            else
            {
                newUrl = url;
            }

            return newUrl;
        }

        public static int CompareByModifiedDate ( BaseEntity x, BaseEntity y )
        {
            if ( y == null )
            {
                if ( x == null )
                    return 0;
                else
                    return -1;
            }
            else
            {
                if ( x == null )
                    return 1;
                else
                {
                    int retval = y.ModifiedDate.CompareTo ( x.ModifiedDate );

                    if ( retval != 0 )
                        return retval;
                    else
                        return y.CreatedDate.CompareTo ( x.CreatedDate );
                }
            }
        }

        public static string FormatCommentText ( string text )
        {
            if ( !string.IsNullOrEmpty ( text ) )
            {
                text = SPHttpUtility.HtmlEncode ( text );
                text = text.Replace ( "\r\n", " <br />" );
            }
            return text;
        }

        public static string ConvertHtmlToKiiroSafeText ( string html )
        {
            string kiiroSafeText = string.Empty;

            if ( !string.IsNullOrEmpty ( html ) )
            {
                if ( html.IndexOf ( '&' ) >= 0 )
                    html = html.Replace ( "&", "&amp;" );

                if (html.IndexOf('<') >= 0)
                    html = html.Replace("<", "&lt;"); 

                kiiroSafeText = SPHttpUtility.ConvertSimpleHtmlToText ( html, -1 );
            }

            return kiiroSafeText;
        }

        public static string UseSSLAltMapping ( string planRelativeUrl, Guid siteCollectionId, string serverRelativeUrl )
        {
            SPWebApplication webApp = null;
            string url = planRelativeUrl;

            try
            {
                using ( SPWeb web = SPHelpers.GetWeb ( siteCollectionId, serverRelativeUrl ) )
                {
                    webApp = SPWebApplication.Lookup ( new Uri ( web.Url ) );
                }

                foreach ( SPAlternateUrl altUrl in webApp.AlternateUrls )
                {
                    if ( altUrl.IncomingUrl.Contains ( "https" ) )
                        url = altUrl.IncomingUrl + planRelativeUrl;
                }
            }
            catch { }
            finally
            {
                if ( webApp != null ) webApp = null;
            }

            return url;
        }

        public static byte [ ] CropImageToSquare ( byte [ ] fileBytes )
        {
            MemoryStream stream = new MemoryStream ( fileBytes );
            System.Drawing.Image userImg = ( System.Drawing.Image ) System.Drawing.Image.FromStream ( stream );

            int width = 0;
            int height = 0;
            int sourceWidth = userImg.Width;
            int sourceHeight = userImg.Height;
            int sourceX = 0;
            int sourceY = 0;
            int destX = 0;
            int destY = 0;

            float nPercent = 0;
            float nPercentW = 0;
            float nPercentH = 0;

            if ( sourceHeight > sourceWidth )
            {
                height = sourceWidth;
                width = sourceWidth;
            }
            else
            {
                height = sourceHeight;
                width = sourceHeight;
            }

            nPercentW = ( ( float ) width / ( float ) sourceWidth );
            nPercentH = ( ( float ) height / ( float ) sourceHeight );

            //Centre crop
            if ( nPercentH < nPercentW )
            {
                nPercent = nPercentW;
                destY = ( int ) ( ( height - ( sourceHeight * nPercent ) ) / 2 );
            }
            else
            {
                nPercent = nPercentH;
                destX = ( int ) ( ( width - ( sourceWidth * nPercent ) ) / 2 );
            }

            int destWidth = ( int ) ( sourceWidth * nPercent );
            int destHeight = ( int ) ( sourceHeight * nPercent );

            Bitmap bmPhoto = new Bitmap ( width, height, PixelFormat.Format24bppRgb );
            bmPhoto.SetResolution ( userImg.HorizontalResolution, userImg.VerticalResolution );

            using (Graphics grPhoto = Graphics.FromImage(bmPhoto))
            {
                grPhoto.InterpolationMode = InterpolationMode.HighQualityBicubic;
                grPhoto.DrawImage(userImg, new Rectangle(destX, destY, destWidth, destHeight), new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight), GraphicsUnit.Pixel);
            }

            MemoryStream m = new MemoryStream ( );
            ImageFormat format = userImg.RawFormat;            
            bmPhoto.Save ( m, format );
            return m.GetBuffer ( );
        }

        public static void CustomSiteColorEdits(Color portalHeadline, Color portalMenu, Color projectHeadline, Color projectMenu, Color links, Color titles, Guid siteCollectionId, string serverRelativeUrl)
        {
            string css = string.Empty;
            Color portalDefaultHeadline = HexToColor("#344c0f");
            Color portalDefaultMenu = HexToColor("#62882d");
            Color projectDefaultHeadline = HexToColor("#134b5b");
            Color projectDefaultMenu = HexToColor("#2c7c98");
            Color defaultLinks = HexToColor("#fa6414");

            using (SPWeb web = SPHelpers.GetPortalWeb(siteCollectionId, serverRelativeUrl))
            {
                #region Portal
                if ((portalHeadline != Color.Empty && portalHeadline != portalDefaultHeadline) || (portalMenu != Color.Empty && portalMenu != portalDefaultMenu))
                {
                    if (portalHeadline == Color.Empty)
                        portalHeadline = portalDefaultHeadline;
                    if (portalMenu == Color.Empty)
                        portalMenu = portalDefaultMenu;

                    web.Files.Add("custom-portal-option-left.jpg", DrawHalfCircle("left", portalHeadline, portalMenu), true);
                    web.Files.Add("custom-portal-option-right.jpg", DrawHalfCircle("right", portalHeadline, portalMenu), true);
                }                

                if (portalHeadline != Color.Empty && portalHeadline != portalDefaultHeadline)
                {
                    Color border = Color.FromArgb(int.Parse((portalHeadline.R * 0.9).ToString().Split('.')[0]),
                        int.Parse((portalHeadline.R * 0.9).ToString().Split('.')[0]),
                        int.Parse((portalHeadline.R * 0.9).ToString().Split('.')[0]));
                    css += "#main #headline { background: none #" + ColorToHex(portalHeadline) + "; border-bottom: #" + ColorToHex(border) + " 1px solid; border-top: #" + ColorToHex(border) + " 1px solid; }" + Environment.NewLine;
                    css += ".pnlCustomColors .portalH { background-color: #" + ColorToHex(portalHeadline) + "; }" + Environment.NewLine;
                }

                if (portalMenu != Color.Empty && portalMenu != portalDefaultMenu)
                {
                    css += "#main #menu { background: url(/_layouts/images/Kiiro/main-menu-border.gif) #" + ColorToHex(portalMenu) + " right bottom repeat-x !important; }" + Environment.NewLine;
                    css += ".pnlCustomColors .portalM { background-color: #" + ColorToHex(portalMenu) + "; }" + Environment.NewLine;
                }

                if ((portalHeadline != Color.Empty && portalHeadline != portalDefaultHeadline) || (portalMenu != Color.Empty && portalMenu != portalDefaultMenu))
                {
                    css += "#main #menu .tcSiteActions li div:hover, #main #menu .options li .selected, #main #menu .options li .selected:hover, #main #menu .options li a:hover { background: url(custom-portal-option-left.jpg) #" + ColorToHex(portalHeadline) + " left top no-repeat !important; }" + Environment.NewLine;
                    css += "#main #menu .tcSiteActions li a:hover, #main #menu .options li a span:hover, #main #menu .options li .selected span, #main #menu .options li .selected span:hover { background: url(custom-portal-option-right.jpg) right top no-repeat !important; }" + Environment.NewLine;
                }
                #endregion

                #region Project
                if ((projectHeadline != Color.Empty && projectHeadline != projectDefaultHeadline) || (projectMenu != Color.Empty && projectMenu != projectDefaultMenu))
                {
                    if (projectHeadline == Color.Empty)
                        projectHeadline = projectDefaultHeadline;
                    if (projectMenu == Color.Empty)
                        projectMenu = projectDefaultMenu;

                    web.Files.Add("custom-project-option-left.jpg", DrawHalfCircle("left", projectHeadline, projectMenu), true);
                    web.Files.Add("custom-project-option-right.jpg", DrawHalfCircle("right", projectHeadline, projectMenu), true);
                }

                if (projectHeadline != Color.Empty && projectHeadline != projectDefaultHeadline)
                {
                    Color border = Color.FromArgb(int.Parse((projectHeadline.R * 0.9).ToString().Split('.')[0]),
                        int.Parse((projectHeadline.R * 0.9).ToString().Split('.')[0]),
                        int.Parse((projectHeadline.R * 0.9).ToString().Split('.')[0]));
                    css += "#project #headline { background: none #" + ColorToHex(projectHeadline) + "; border-bottom: #" + ColorToHex(border) + " 1px solid; border-top: #" + ColorToHex(border) + " 1px solid; }" + Environment.NewLine;
                    css += ".pnlCustomColors .projectH { background-color: #" + ColorToHex(projectHeadline) + "; }" + Environment.NewLine;
                }

                if (projectMenu != Color.Empty && projectMenu != projectDefaultMenu)
                {
                    css += "#project #menu  { background: url(/_layouts/images/Kiiro/main-menu-border.gif) #" + ColorToHex(projectMenu) + " right bottom repeat-x !important; }" + Environment.NewLine;
                    css += ".pnlCustomColors .projectM { background-color: #" + ColorToHex(projectMenu) + "; }" + Environment.NewLine;
                }

                if ((projectHeadline != Color.Empty && projectHeadline != projectDefaultHeadline) || (projectMenu != Color.Empty && projectMenu != projectDefaultMenu))
                {
                    css += "#project #menu .tcSiteActions li div:hover, #project #menu .options li .selected, #project #menu .options li .selected:hover, #project #menu .options li a:hover { background: url(custom-project-option-left.jpg) #" + ColorToHex(projectHeadline) + " left top no-repeat !important; }" + Environment.NewLine;
                    css += "#project #menu .tcSiteActions li a:hover, #project #menu .options li a span:hover, #project #menu .options li .selected span, #project #menu .options li .selected span:hover { background: url(custom-project-option-right.jpg) right top no-repeat !important; }" + Environment.NewLine;
                }
                #endregion

                #region Global Colors
                if (links != Color.Empty && links != defaultLinks)
                {
                    css += ".pnlCustomColors .linkBG { background-color: #" + ColorToHex(links) + "; }" + Environment.NewLine;
                    css += "a, #content .jq_carousel LI DL DD SPAN.userNameLink { color: #" + ColorToHex(links) + "; }" + Environment.NewLine;
                }

                if(titles != Color.Empty && titles != defaultLinks)
                {
                    css += ".pnlCustomColors .titleBG { background-color: #" + ColorToHex(titles) + "; }" + Environment.NewLine;
                    css += "#content .body .panel .settings .row DT, #content .body .panel .project .timeline DD, #content .body .panel .comment .comment-body .comment-title H3, #content .body .panel .settings .status-wrap .status-progress DD, #content .body .panel .table .status-wrap .status-progress DD  { color: #" + ColorToHex(titles) + " !important; }" + Environment.NewLine;
                }
                #endregion

                System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
                web.Files.Add("kiiro-custom.css", encoding.GetBytes(css), true);
            }
        }

        private static byte[] DrawHalfCircle(string side, Color primary, Color secondary)
        {
            int w = 32; 
            int h = 27;
            int s = 14;

            Bitmap bitmap = new Bitmap(w, h);

            using (Graphics gfx = Graphics.FromImage(bitmap))
            {
                gfx.SmoothingMode = SmoothingMode.HighQuality;
                gfx.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
                gfx.CompositingQuality = CompositingQuality.HighQuality;
                gfx.InterpolationMode = InterpolationMode.HighQualityBicubic;    
                gfx.DrawRectangle(new Pen(secondary), 0, 0, w, h);
                gfx.FillRectangle(new SolidBrush(secondary), 0, 0, w, h);
                gfx.FillEllipse(new SolidBrush(primary), 0, 0, w, h - 1);
            }

            bitmap = bitmap.Clone(new Rectangle(0, 2, s, h - 3), bitmap.PixelFormat);            
            
            if (side != "left")
                bitmap.RotateFlip(RotateFlipType.RotateNoneFlipX);          

            ImageCodecInfo jpegEncoderInfo = null;
            ImageCodecInfo[] encoderInfoArray = ImageCodecInfo.GetImageEncoders();

            foreach (ImageCodecInfo imageCodecInfo in encoderInfoArray)            
                if(imageCodecInfo.MimeType == "image/jpeg")                
                    jpegEncoderInfo = imageCodecInfo;            
            
            EncoderParameters encoderParameters = new EncoderParameters(1);
            encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L);

            MemoryStream m = new MemoryStream();
            bitmap.Save(m, jpegEncoderInfo, encoderParameters);        

            return m.GetBuffer();
        }

        public static Color HexToColor(string hex)
        {
            Color color = Color.Empty;

            if (!string.IsNullOrEmpty(hex))
            {
                hex = hex.Trim();

                int r = 0;
                int g = 0;
                int b = 0;

                if (hex.StartsWith("rgb("))
                {
                    hex = hex.Split('(')[1];
                    hex = hex.Split(')')[0];
                    r = int.Parse(hex.Split(',')[0]);
                    g = int.Parse(hex.Split(',')[1]);
                    b = int.Parse(hex.Split(',')[2]);
                }
                else
                {
                    if (hex.StartsWith("#"))
                        hex = hex.Substring(1);

                    r = int.Parse(hex.Substring(0, 2), NumberStyles.HexNumber);
                    g = int.Parse(hex.Substring(2, 2), NumberStyles.HexNumber);
                    b = int.Parse(hex.Substring(4, 2), NumberStyles.HexNumber);
                }

                color = Color.FromArgb(r, g, b);
            }

            return color;
        }

        public static string ColorToHex(Color color)
        {
            string hex = string.Empty;

            string r = color.R.ToString("X");
            r = r.Length < 2 ? "0" + r : r;
            string g = color.G.ToString("X");
            g = g.Length < 2 ? "0" + g : g;
            string b = color.B.ToString("X");
            b = b.Length < 2 ? "0" + b : b;

            hex = r + g + b;

            return hex;
        }

        public static bool IsFormsBasedAuthenticationEnabled ( Guid siteCollectionId, string serverRelativeUrl )
        {
            bool isFBAEnabled = false;

            try
            {
                string webUrl = GetAbsoluteUrl ( siteCollectionId, serverRelativeUrl );
                SPWebApplication webApplication = SPWebApplication.Lookup ( new Uri ( webUrl ) );

                if ( webApplication.IisSettings
                    .Count ( x => ( ( SPIisSettings ) x.Value ).MembershipProvider == Permissions.FBAMembershipProviderName ) > 0 )
                {
                    isFBAEnabled = true;
                }
            }
            catch ( Exception ex )
            {
                isFBAEnabled = false;
                ExceptionManager.HandleException ( ex, false );
            }

            return isFBAEnabled;
        }


        public static List<KiiroGroup> GetUserGroups ( string login, Guid siteCollectionId, string serverRelativeUrl )
        {
            List<KiiroGroup> userGroups = new List<KiiroGroup> ( );
            bool originalCADE = SPSecurity.CatchAccessDeniedException;

            try
            {
                /* Don't catch access denied exceptions while running this code because:
                 *      a) This method is called when populating EVERY user entity, and if we are loading a 'login' 
                 *          that is not a member of the web we'll get an access denied exception.
                 *      b) We can't run this elevated. We'll need to be impersonating 'login' in order to make use
                 *          of SPGroup.ContainsCurrentUser method. This method is the only one that can tell 
                 *          us if 'login' is a member of the SPGroup through an AD group
                 */
                SPSecurity.CatchAccessDeniedException = false;

                if ( siteCollectionId != Guid.Empty && serverRelativeUrl != null )
                {
                    using ( SPWeb web = GetWeb ( siteCollectionId, serverRelativeUrl, login ) )
                    {
                        if ( IsPortal ( web ) )
                        {
                            if ( web.AssociatedOwnerGroup != null && web.AssociatedOwnerGroup.ContainsCurrentUser )
                                userGroups.Add ( KiiroGroup.PortalOwner );

                            if ( web.AssociatedMemberGroup != null && web.AssociatedMemberGroup.ContainsCurrentUser )
                                userGroups.Add ( KiiroGroup.PortalMember );

                            if ( web.AssociatedVisitorGroup != null && web.AssociatedVisitorGroup.ContainsCurrentUser )
                                userGroups.Add ( KiiroGroup.Visitor );
                        }
                        else if ( IsProject ( web ) )
                        {
                            using ( SPWeb parentWeb = web.ParentWeb )
                            {
                                if ( parentWeb.AssociatedOwnerGroup != null && parentWeb.AssociatedOwnerGroup.ContainsCurrentUser )
                                    userGroups.Add ( KiiroGroup.PortalOwner );

                                if ( parentWeb.AssociatedMemberGroup != null && parentWeb.AssociatedMemberGroup.ContainsCurrentUser )
                                    userGroups.Add ( KiiroGroup.PortalMember );

                                if ( web.AssociatedOwnerGroup != null && web.AssociatedOwnerGroup.ContainsCurrentUser )
                                    userGroups.Add ( KiiroGroup.ProjectOwner );

                                if ( web.AssociatedMemberGroup != null && web.AssociatedMemberGroup.ContainsCurrentUser )
                                    userGroups.Add ( KiiroGroup.ProjectMember );

                                if ( web.AssociatedVisitorGroup != null && web.AssociatedVisitorGroup.ContainsCurrentUser )
                                    userGroups.Add ( KiiroGroup.Visitor );
                            }
                        }
                    }
                }
            }
            catch ( UnauthorizedAccessException ex )
            {
                string notes = string.Format ( "User: {0} does not have access to web: {1}", login, serverRelativeUrl );
                ExceptionManager.HandleException ( ex, false, notes );
            }
            catch ( Exception ex )
            {
                ExceptionManager.HandleException ( ex, false );
            }
            finally
            {
                SPSecurity.CatchAccessDeniedException = originalCADE;
            }

            return userGroups;
        }

        public static List<KiiroGroup> GetUserGroupsExplicit ( string login, Guid siteCollectionId, string serverRelativeUrl )
        {
            List<KiiroGroup> userGroups = new List<KiiroGroup> ( );
            bool originalCADE = SPSecurity.CatchAccessDeniedException;

            try
            {
                /* Don't catch access denied exceptions while running this code because:
                 *      a) This method is called when populating EVERY user entity, and if we are loading a 'login' 
                 *          that is not a member of the web we'll get an access denied exception.
                 *      b) We can't run this elevated. We'll need to be impersonating 'login' in order to make use
                 *          of SPGroup.ExplicitlyContainsCurrentUser method. This method is the only one that can tell 
                 *          us if 'login' is a member of the SPGroup through an AD group
                 */
                SPSecurity.CatchAccessDeniedException = false;

                if ( siteCollectionId != Guid.Empty && serverRelativeUrl != null )
                {
                    using ( SPWeb web = GetWeb ( siteCollectionId, serverRelativeUrl, login ) )
                    {
                        if ( IsPortal ( web ) )
                        {
                            if ( web.AssociatedOwnerGroup != null && web.AssociatedOwnerGroup.ExplicitlyContainsCurrentUser )
                                userGroups.Add ( KiiroGroup.PortalOwner );

                            if ( web.AssociatedMemberGroup != null && web.AssociatedMemberGroup.ExplicitlyContainsCurrentUser )
                                userGroups.Add ( KiiroGroup.PortalMember );

                            if ( web.AssociatedVisitorGroup != null && web.AssociatedVisitorGroup.ExplicitlyContainsCurrentUser )
                                userGroups.Add ( KiiroGroup.Visitor );
                        }
                        else if ( IsProject ( web ) )
                        {
                            using ( SPWeb parentWeb = web.ParentWeb )
                            {
                                if ( parentWeb.AssociatedOwnerGroup != null && parentWeb.AssociatedOwnerGroup.ExplicitlyContainsCurrentUser )
                                    userGroups.Add ( KiiroGroup.PortalOwner );

                                if ( parentWeb.AssociatedMemberGroup != null && parentWeb.AssociatedMemberGroup.ExplicitlyContainsCurrentUser )
                                    userGroups.Add ( KiiroGroup.PortalMember );

                                if ( web.AssociatedOwnerGroup != null && web.AssociatedOwnerGroup.ExplicitlyContainsCurrentUser )
                                    userGroups.Add ( KiiroGroup.ProjectOwner );

                                if ( web.AssociatedMemberGroup != null && web.AssociatedMemberGroup.ExplicitlyContainsCurrentUser )
                                    userGroups.Add ( KiiroGroup.ProjectMember );

                                if ( web.AssociatedVisitorGroup != null && web.AssociatedVisitorGroup.ExplicitlyContainsCurrentUser )
                                    userGroups.Add ( KiiroGroup.Visitor );
                            }
                        }
                    }
                }
            }
            catch ( UnauthorizedAccessException ex )
            {
                string notes = string.Format ( "User: {0} does not have access to web: {1}", login, serverRelativeUrl );
                ExceptionManager.HandleException ( ex, false, notes );
            }
            catch ( Exception ex )
            {
                ExceptionManager.HandleException ( ex, false );
            }
            finally
            {
                SPSecurity.CatchAccessDeniedException = originalCADE;
            }

            return userGroups;
        }

        public static int GetSPUserId ( string login, Guid siteCollectionId, string serverRelativeUrl )
        {
            int spUserId = default ( int );
            bool originalCADE = SPSecurity.CatchAccessDeniedException;

            try
            {
                /* Don't catch access denied exceptions while running this code because:
                 *      a) This method is called when populating EVERY user entity, and if we are loading a 'login' 
                 *          that is not a member of the web we'll get an access denied exception.
                 *      b) We can't run this elevated. We'll need to be impersonating 'login' in order to make use
                 *          of SPGroup.ContainsCurrentUser method. This method is the only one that can tell 
                 *          us if 'login' is a member of the SPGroup through an AD group
                 */
                SPSecurity.CatchAccessDeniedException = false;

                if ( siteCollectionId != Guid.Empty && serverRelativeUrl != null )
                {
                    using ( SPWeb web = GetWeb ( siteCollectionId, serverRelativeUrl, login ) )
                    {
                        spUserId = web.CurrentUser.ID;
                    }
                }
            }
            catch ( UnauthorizedAccessException ex )
            {
                string notes = string.Format ( "User: {0} does not have access to web: {1}", login, serverRelativeUrl );
                ExceptionManager.HandleException ( ex, false, notes );
            }
            catch ( Exception ex )
            {
                ExceptionManager.HandleException ( ex, false );
            }
            finally
            {
                SPSecurity.CatchAccessDeniedException = originalCADE;
            }

            return spUserId;
        }

        public static string CheckTextForLinks ( string textValue )
        {
            textValue = textValue ?? "";
            string reg = @"((https?|ftp|gopher|telnet|file|notes|ms-help):((//)|(\\\\))+[\w\d:#@%/;$()~_?\+-=\\\.&]*)";
            Match match = new Regex ( reg ).Match ( textValue );

            foreach (Capture capture in match.Captures)
            {
                textValue = textValue.Replace ( capture.Value, string.Format ( "<a href='{0}'>{0}</a>", capture.Value ) );
            }

            return textValue;
        }

        public static string Truncate ( string text, int length, string append )
        {
            // Adapted from code found at http://stackoverflow.com/questions/1714764 
            XmlDocument xml = new XmlDocument ( );

            xml.LoadXml ( string.Format ( "<root>{0}</root>", text.Replace ( "&", "&amp;" ) ) );

            // create a navigator, this is our primary tool 
            XPathNavigator navigator = xml.CreateNavigator ( );
            XPathNavigator breakPoint = null;

            string lastText = "";
            bool truncated = false;

            // find the text node we need: 
            while ( navigator.MoveToFollowing ( XPathNodeType.Text ) )
            {
                lastText = navigator.Value.Substring ( 0, (int) Math.Min ( length, navigator.Value.Length ) );
                length -= navigator.Value.Length;

                if ( length <= 0 )
                {
                    // truncate the last text. Here goes your "search word boundary" code: 
                    truncated = true;
                    navigator.SetValue ( lastText );
                    breakPoint = navigator.Clone ( );
                    break;
                }
            }

            // first remove text nodes, because Microsoft unfortunately merges them without asking 
            while ( navigator.MoveToFollowing ( XPathNodeType.Text ) )
                if ( navigator.ComparePosition ( breakPoint ) == XmlNodeOrder.After )
                    navigator.DeleteSelf ( );   // moves to parent 

            // then move the rest 
            navigator.MoveTo ( breakPoint );
            while ( navigator.MoveToFollowing ( XPathNodeType.Element ) )
                if ( navigator.ComparePosition ( breakPoint ) == XmlNodeOrder.After )
                    navigator.DeleteSelf ( );   // moves to parent 

            // then remove *all* empty nodes to clean up (not necessary):  
            // TODO, add empty elements like <br />, <img /> as exclusion 
            navigator.MoveToRoot ( );
            while ( navigator.MoveToFollowing ( XPathNodeType.Element ) )
                while ( !navigator.HasChildren && ( navigator.Value ?? "" ).Trim ( ) == "" )
                    navigator.DeleteSelf ( );  // moves to parent 

            navigator.MoveToRoot ( );
                        
            xml.LoadXml ( navigator.InnerXml );

            if ( truncated )
            {
                XmlNodeList nodesWithText = xml.SelectNodes ( "//*[text()]" );
                if ( nodesWithText != null && nodesWithText.Count>0 )
                    nodesWithText.Cast<XmlNode>().Last().InnerText += append;
            }

            return xml.DocumentElement.InnerXml;
        }
    }
}

/*************************************************************************
 * 
 * $Log: /Internal Projects/Kiiro/Kiiro.Common/Utility/SPHelpers.cs $
 * 
 * 53    2/23/10 11:42a Camerons
 * 
 * 52    2/08/10 5:04p Camerons
 * 
 * 51    1/25/10 1:17p Camerons
 * 
 * 50    1/18/10 1:36p Camerons
 * 
 * 49    1/12/10 2:33p Camerons
 * 
 * 48    1/12/10 12:02p Camerons
 * 
 * 47    12/16/09 4:05p Stefanf
 * 
 * 46    26/11/09 10:35a Camerons
 * 
 * 45    19/11/09 5:00p Camerons
 * 
 * 44    17/11/09 6:46p Camerons
 * 
 * 43    17/11/09 10:17a Shafia
 * 
 * 42    7/11/09 3:50p Camerons
 * 
 * 41    7/11/09 3:24p Camerons
 * 
 * 40    7/11/09 2:41p Camerons
 * 
 * 39    6/11/09 12:40p Camerons
 * 
 * 38    2/11/09 6:22p Camerons
 * 
 * 37    28/10/09 10:32p Camerons
 * 
 * 36    27/10/09 10:27a Camerons
 * 
 * 35    27/10/09 10:26a Camerons
 * 
 * 34    26/10/09 5:36p Shafia
 * added CheckTextForLinks(string textValue) to check for links within a
 * text
 * 
 * 33    26/10/09 10:38a Camerons
 * 
 * 32    10/23/09 5:00p Adamw
 * Case 348, added ConvertHtmlToKiiroSafeText([text]) to replace
 * SPHttpUtility.ConvertSimpleHtmlToText([text], -1 ), SP method looking
 * for &...; and not finding it resulting in truncated text
 * 
 * 31    10/19/09 7:01p Adamw
 * Case 349a, wrapped href = " instead of ' to allow for ' in filenames
 * and ripple of change
 * 
 * 30    15/10/09 12:26p Camerons
 * Added some null checks and descriptive error messages to IsInKiiroGroup
 * and IsInKiiroGroupExplicit
 * 
 * 29    15/10/09 9:34a Camerons
 * 
 * 28    10/08/09 1:16p Stefanf
 * 
 * 27    10/07/09 7:34p Adamw
 * Case: 288, enhanced the check if ability to add Froms user should be
 * displayed.
 * 
 * 26    7/10/09 5:14p Camerons
 * Case #281, #285: Update SPDataHelpers.MakeUser to take SiteCollectionId
 * and ServerRelativeUrl as params. Used to properly determine the group
 * memberships.
 * 
 * 25    5/10/09 11:07a Camerons
 * RE: Create user on demand, checks for HasUnlimitedUser before creating
 * 
 * 24    29/09/09 1:22p Camerons
 * Implementing User.SPUserId
 * 
 * 23    29/09/09 10:41a Camerons
 * 
 * 22    22/09/09 6:03p Camerons
 * Code changes to support creating user on demand - version 1.1.x.x
 * 
 * 21    21/09/09 12:02p Camerons
 * IsProject(SPWeb web) and IsPortal(SPWeb web) - don't dispose the web,
 * that's the resposibility of the calling method
 * 
 * 20    4/09/09 10:24a Camerons
 * 
 * 19    3/09/09 11:34a Camerons
 * Refactored GetSystemSite to use RWEP if (and only if) an access denied
 * is thrown when trying to get the system token
 * 
 * 18    2/09/09 4:35p Camerons
 * Added GetSiteUrl method
 * 
 * 17    31/08/09 11:56a Camerons
 * 
 * 16    26/08/09 3:11p Shafia
 * 
 * 15    24/08/09 2:31p Camerons
 * 
 * 14    8/19/09 3:18p Camerons
 * 
 * 13    17/08/09 10:38a Camerons
 * Added check-in comments section
 * 
 ************************************************************************/